// const defaultConfig = {
//     protocol: 'ws',
//     hostname: 'localhost',
//     port: '3000',
//     timeout: 3000,  // 心跳保活
//     curReconnectCount: 0,
//     maxReconnectCount: 2,
//     reconnectTime: 30000,
//     heartCheckInfo: heartCheckInfo,
//     heartCheckType: heartCheckType,
//     openCallback: openCallback,
//     messageCallback: messageCallback,
//     closeCallback: closeCallback,
//     errorCallback: errorCallback,
// }

/* 实现功能 */
// 1、webSocket 连接、关闭
// 2、业务逻辑传入处理
// 3、心跳保活
// 4、断开连接重连（正常退出除外）
class MyWebSocket {
	constructor(serviceName, config) {
		this.serviceName = serviceName
		this.config = config
		this.ws = null
		this.reconnectTimer = null
		this.heartCheck = {
			timeout: config.timeout, //30秒发一次心跳
			timeoutObj: null,
			serverTimeoutObj: null,
			reset: function () {
				clearTimeout(this.timeoutObj)
				clearTimeout(this.serverTimeoutObj)
				return this
			},
			start: function (ws) {
				const self = this
				this.timeoutObj = setTimeout(function () {
					//这里发送一个心跳，后端收到后，返回一个心跳消息，
					//onmessage拿到返回的心跳就说明连接正常
					ws.send(JSON.stringify(config.heartCheckInfo))

					self.serverTimeoutObj = setTimeout(function () {
						//如果超过一定时间还没重置，说明后端主动断开了
						ws.close()
					}, self.timeout)
				}, this.timeout)
			},
		}
		this.initWebSocket()
	}

	initWebSocket() {
		console.log('重连')
		const { protocol, hostname, port } = this.config
		this.ws = new WebSocket(`${protocol}://${hostname}:${port}`)

		this.ws.addEventListener('open', this.handleOpen)
		this.ws.addEventListener('message', this.handleMessage)
		this.ws.addEventListener('close', this.handleClose)
		this.ws.addEventListener('error', this.handleError)

		// 心跳保活
		this.heartCheck.start(this.ws)
	}

	handleError = (e) => {
		console.log('e', e)
		this.config.errorCallback(e)
	}

	handleOpen = (e) => {
		this.config.openCallback(e)
	}

	handleClose = (e) => {
		// 清除定时器
		this.heartCheck.reset()
		// 解绑事件
		this.ws.removeEventListener('open', this.handleOpen)
		this.ws.removeEventListener('message', this.handleMessage)
		this.ws.removeEventListener('close', this.handleClose)
		e && this.config.closeCallback(e)

		e && this.reconnect()
	}

	handleMessage = (e) => {
		/* 模拟手动关闭websocket, 不传参数 e ,不需要重连 */
		// setTimeout(() => {
		//     this.handleClose()
		// })

		// 后端推送待办数量，并在前端显示
		if (e.data) {
			const message = JSON.parse(e.data)
			if (message.type === heartCheckType) {
				console.log('[receive server message]:', message)
				this.heartCheck.reset().start(this.ws)
			} else {
				this.config.messageCallback(e)
			}
		}
	}

	// 后端服务出现错误后，会重连，错误会被 error 事件监听
	reconnect = () => {
		this.reconnectTimer = setTimeout(() => {
			this.config.curReconnectCount++
			if (this.config.curReconnectCount > this.config.maxReconnectCount) {
				clearTimeout(this.reconnectTimer)
				return
			}

			this.initWebSocket()
		}, this.config.reconnectTime)
	}
}
